#include "esp_system.h"
#include "esp_log.h"
#include "driver/gpio.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define GPIO_CE			GPIO_NUM_2
#define GPIO_RESET		GPIO_NUM_4
#define GPIO_DC			GPIO_NUM_5
#define GPIO_DIN		GPIO_NUM_18
#define GPIO_CLK		GPIO_NUM_19
#define GPIO_BL			GPIO_NUM_21

// delay seconds
#define DELAY(s)		{vTaskDelay(1000 * s / portTICK_RATE_MS);}

static const char *TAG = "main";

uint8_t shuzi[]={
/*--  letter:  0  --*/
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,

/*--  letter:  1  --*/
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,

/*--  letter:  2  --*/
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,

/*--  letter:  3  --*/
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,

/*--  letter:  4  --*/
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,

/*--  letter:  5  --*/
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,

/*--  letter:  6  --*/
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,

/*--  letter:  7  --*/
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,

/*--  letter:  8  --*/
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,

/*--  letter:  9  --*/
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,

/*--  letter:  a  --10*/
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,

/*--  letter:  b  --11*/
0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,

/*--  letter:  c  --12*/
0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,

/*--  letter:  d  --13*/
0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,

/*--  letter:  e  --*/
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,

/*--  letter:  f  --*/
0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,

/*--  letter:  g  --16*/
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,

/*--  letter:  h  --*/
0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,

/*--  letter:  i  --*/
0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,

/*--  letter:  j  --19*/
0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,

/*--  letter:  k  --*/
0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,

/*--  letter:  l  --*/
0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,

/*--  letter:  m  --22*/
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,

/*--  letter:  n  --23*/
0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,

/*--  letter:  o  --24*/
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,

/*--  letter:  p  --*/
0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,

/*--  letter:  q  --*/
0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,

/*--  letter:  r  --*/
0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,
																			   
/*--  letter:  s  --*/
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,

/*--  letter:  t  --*/
0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,

/*--  letter:  u  --30*/
0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,

/*--  letter:  v  --*/
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,

/*--  letter:  w  --*/
0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,

/*--  letter:  x  --*/
0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,

/*--  letter:  y  --*/
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,

/*--  letter:  z  --35*/
0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,

/*--  letter:  -  --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,

/*--  letter:  =  --*/
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,

/*--  letter:  \  --*/
0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,

/*--  letter:     --39*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

/*--  letter:  [  --*/
0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,

/*--  letter:  ]  --*/
0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,

/*--  letter:  ;  --*/
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,

/*--  letter:  '  --*/
0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

/*--  letter:  ,  --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,

/*--  letter:  .  --45*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,

/*--  letter:  /  --*/
0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,
	
};

void lcd_write_byte(uint8_t dat, uint8_t command)
{
	int i;
	gpio_set_level(GPIO_CE, 0);
	gpio_set_level(GPIO_DC, command);
	for(i = 0; i < 8; i++) { 
		if(dat & 0x80) {
			gpio_set_level(GPIO_DIN, 1);
		} else {
			gpio_set_level(GPIO_DIN, 0);
		}
		dat = dat << 1;
		gpio_set_level(GPIO_CLK, 0);
		gpio_set_level(GPIO_CLK, 1);
	}
	gpio_set_level(GPIO_DC, 1);
	gpio_set_level(GPIO_CE, 1);
	gpio_set_level(GPIO_DIN, 1);
}

void pin_init(void)
{
	int i;
	gpio_num_t pins[] = {
		GPIO_CE,
		GPIO_RESET,
		GPIO_DC,
		GPIO_DIN,
		GPIO_CLK,
		GPIO_BL
	};
	
	gpio_config_t conf = { 
		.mode = GPIO_MODE_OUTPUT, 
		.pull_up_en = GPIO_PULLUP_DISABLE, 
		.pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE
	};

	for (i = 0; i < sizeof(pins) / sizeof(gpio_num_t); ++i) {
        conf.pin_bit_mask = 1LL << pins[i];
        gpio_config(&conf);
    }
}

void lcd_init(void)
{
	ESP_LOGI(TAG, "LCD init");
	gpio_set_level(GPIO_BL, 1);
	lcd_write_byte(0x21,0);
	lcd_write_byte(0xd0,0);
	lcd_write_byte(0x20,0);
	lcd_write_byte(0x0C,0);
}

void lcd_set_xy(unsigned char x, unsigned char y)
{
	lcd_write_byte(0x40 | y, 0);// column
	lcd_write_byte(0x80 | x, 0);// row
}

void clear_screen(void)
{
	uint8_t t, k;
	lcd_set_xy(0, 0);
	for(t = 0; t < 6; t++) { 
		for(k = 0; k < 84; k++) { 
			lcd_write_byte(0x00, 1);
		} 
	}
}

void lcd_write_letter(uint8_t row, uint8_t page, uint8_t c)
{
	int i;  	
	
	lcd_set_xy(row*8, page);
	for(i = 0; i < 8; i++) {
		lcd_write_byte(shuzi[c*16+i],1); 
	}
	
    lcd_set_xy(row*8, page+1);
	for(i = 8; i < 16; i++) {
		lcd_write_byte(shuzi[c*16+i],1);
	}	
}

void app_main()
{
	DELAY(1);
	gpio_set_level(GPIO_RESET, 0);
	DELAY(0.5);
	gpio_set_level(GPIO_RESET, 1);
	DELAY(0.5);
	pin_init();
	lcd_init();
	clear_screen();


	/*lcd_write_letter(1, 2, 13); 	//d
	lcd_write_letter(2, 2, 24); 	//o
	lcd_write_letter(3, 2, 18); 	//i
	lcd_write_letter(4, 2, 29); 	//t
	lcd_write_letter(5, 2, 45);		//.
	lcd_write_letter(6, 2, 10);		//a
	lcd_write_letter(7, 2, 22); 	//m
	*/
	lcd_write_letter(1, 1, 17); 	//h
	lcd_write_letter(2, 1, 14); 	//e
	lcd_write_letter(3, 1, 21); 	//l
	lcd_write_letter(4, 1, 21); 	//l
	lcd_write_letter(5, 1, 24); 	//o
	lcd_write_letter(3, 3, 32); 	//w
	lcd_write_letter(4, 3, 24); 	//o
	lcd_write_letter(5, 3, 27); 	//r
	lcd_write_letter(6, 3, 21); 	//l
	lcd_write_letter(7, 3, 13); 	//d

	while (1) {
		ESP_LOGI(TAG, "main loop");
		DELAY(3);
	}
}